package dominio;

import java.io.InputStream;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

@Entity
@Table(name = "solicitudArticulo", uniqueConstraints = { @UniqueConstraint(columnNames = {
		"idSolicitud", "idModulo" }) })
public class SolicitudArticulo implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6306833224171489096L;

	@Id
	@GeneratedValue
	private Long codigo;

	// es el id de la solicitud del modulo de despacho
	private Long idSolicitud;
	// es numero de equipo de despacho
	private Long idModulo;

	private Date fecha;

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "solicitudArticulo", orphanRemoval = true, fetch = FetchType.EAGER)
	private List<ArticuloItem> articulosItems;

	private Estado estado;

	public SolicitudArticulo() {
		estado = Estado.CREADA;
		fecha = new Date();
	}

	public SolicitudArticulo(Long idSolicitud, Long idModulo) {
		this();
		this.idSolicitud = idSolicitud;
		this.idModulo = idModulo;
	}

	public List<ArticuloItem> getArticulosItems() {
		return articulosItems;
	}

	public void setArticulosItems(List<ArticuloItem> articulosItems) {
		this.articulosItems = articulosItems;
	}

	public Long getIdSolicitud() {
		return idSolicitud;
	}

	public void setIdSolicitud(Long idSolicitud) {
		this.idSolicitud = idSolicitud;
	}

	public Long getIdModulo() {
		return idModulo;
	}

	public void setIdModulo(Long idModulo) {
		this.idModulo = idModulo;
	}

	public Estado getEstado() {
		return estado;
	}

	public Long getCodigo() {
		return codigo;
	}

	public String getFechaString() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return sdf.format(fecha);
	}

	public Date getFecha() {
		return fecha;
	}

	public void entregar() {
		for (ArticuloItem articuloItem : articulosItems) {
			if (!articuloItem.entregado()) {
				return;
			}
		}
		this.estado = Estado.ENTREGADA;
	}
	
	public void entregar(Set<ArticuloItem> articuloItemsUpdate) {
		this.articulosItems.clear();
		this.articulosItems.addAll(articuloItemsUpdate);
		entregar();
	}

	public void aFabricar() {
		this.estado = Estado.PARA_FABRICAR;
	}

	public void aEntregar() {
		this.estado = Estado.PARA_ENVIAR;
	}

	public boolean estaEntregada() {
		return Estado.ENTREGADA.equals(estado);
	}

	public boolean estaCreada() {
		return Estado.CREADA.equals(estado);
	}

	public boolean estaParaEnviar() {
		return Estado.PARA_ENVIAR.equals(estado);
	}

	public boolean estaParaFabricar() {
		return Estado.PARA_FABRICAR.equals(estado);
	}

	public boolean estaPendiente() {
		return Estado.PARA_ENVIAR.equals(estado)
				|| Estado.PARA_FABRICAR.equals(estado);
	}

	/**
	 * Parseo el xml entero de la solicitud de articulos
	 * 
	 * @param articuloXml
	 * @return
	 */
	public static SolicitudArticulo leer(InputStream articuloXml) {
		SolicitudArticulo solicitudArticulo = null;
		try {

			// File fXmlFile = new File("/Users/mkyong/staff.xml");

			DocumentBuilderFactory dbFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(articuloXml);

			doc.getDocumentElement().normalize();

			System.out.println("Root element :"
					+ doc.getDocumentElement().getNodeName());

			// Tomo la idSolicitud
			String idSolicitudElement = doc.getElementsByTagName("idSolicitud")
					.item(0).getTextContent();

			// Tomo el id de modulo
			String idModuloElement = doc.getElementsByTagName("idModulo")
					.item(0).getTextContent();

			solicitudArticulo = new SolicitudArticulo(
					Long.valueOf(idSolicitudElement),
					Long.valueOf(idModuloElement));

			System.out.println(solicitudArticulo);

			// Tomo la lista de los articulos
			List<ArticuloItem> articuloItems = parseArticulos(doc,
					solicitudArticulo);

			solicitudArticulo.setArticulosItems(articuloItems);

		} catch (Exception e) {
			e.printStackTrace();
		}
		return solicitudArticulo;
	}

	/**
	 * parseo el articulo item del xml
	 * 
	 * @param doc
	 * @param solicitudArticulo
	 * @return
	 */
	private static List<ArticuloItem> parseArticulos(Document doc,
			SolicitudArticulo solicitudArticulo) {

		List<ArticuloItem> articuloItems = new ArrayList<ArticuloItem>();

		NodeList nList = doc.getElementsByTagName("articulos");

		System.out.println("----------------------------");

		Node nNode = nList.item(0);

		System.out.println("\nCurrent Element :" + nNode.getNodeName());

		if (nNode.getNodeType() == Node.ELEMENT_NODE) {
			Element eElement = (Element) nNode;

			NodeList childNodes = eElement.getElementsByTagName("articulo");

			for (int temp = 0; temp < childNodes.getLength(); temp++) {

				Node cNode = childNodes.item(temp);

				System.out.println("\nCurrent Element :" + cNode.getNodeName());

				ArticuloItem articuloItem = null;

				if (nNode.getNodeType() == Node.ELEMENT_NODE) {

					Element articuloElement = (Element) nNode;

					// System.out.println("Staff id : "
					// + eElement.getAttribute("id"));

					String codigo = articuloElement
							.getElementsByTagName("codigo").item(temp)
							.getTextContent();
					System.out.println("Codigo : " + codigo);

					String cantidad = articuloElement
							.getElementsByTagName("cantidad").item(temp)
							.getTextContent();
					System.out.println("Cantidad : " + cantidad);

					articuloItem = new ArticuloItem(Long.valueOf(codigo),
							Integer.valueOf(cantidad), solicitudArticulo);
					if (articuloItem != null)
						articuloItems.add(articuloItem);
				}
			}
		}
		return articuloItems;
	}

	@Override
	public String toString() {
		return "SolicitudArticulo ["
				+ (codigo != null ? "codigo=" + codigo + ", " : "")
				+ (idSolicitud != null ? "idSolicitud=" + idSolicitud + ", "
						: "")
				+ (idModulo != null ? "idModulo=" + idModulo + ", " : "")
				+ (articulosItems != null ? "articulosItems=" + articulosItems
						+ ", " : "")
				+ (estado != null ? "estado=" + estado : "") + "]";
	}

	public ArticuloItem findArticuloItem(Long codigoArticulo) {
		for (ArticuloItem articuloItem : this.articulosItems) {
			if (articuloItem.getCodigoArticulo().equals(codigoArticulo)) {
				return articuloItem;
			}
		}
		return null;
	}
}
